/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <A_CUDA数学Core/mat44.h>
//#include <A_CUDA数学Core/mat33.h>
#include <A_CUDA数学Core/Vec3.h>
#include <A_CUDA数学Core/Vec4.h>
#include <A_CUDA数学Core/maths.h>

#include <矩阵.h>
#include <向量.h>

#include "几何计算.h"
#include "matXX.h"




// convenience
typedef Mat44 C_Mat44;
typedef Matrix33 C_Mat33;




CUDA_CALLABLE inline vec3 f_Multiply(const C_Mat44& mat, const vec3& v) {
	vec3 r;
	r.x = v.x*mat[0] + v.y*mat[4] + v.z*mat[8] + mat[12];
	r.y = v.x*mat[1] + v.y*mat[5] + v.z*mat[9] + mat[13];
	r.z = v.x*mat[2] + v.y*mat[6] + v.z*mat[10] + mat[14];
	return r;
}

CUDA_CALLABLE inline vec4 f_Multiply(const C_Mat44& mat, const vec4& v) {
	vec4 r;
	r.x = v.x * mat[0] + v.y * mat[4] + v.z * mat[8] + mat[12];
	r.y = v.x * mat[1] + v.y * mat[5] + v.z * mat[9] + mat[13];
	r.z = v.x * mat[2] + v.y * mat[6] + v.z * mat[10] + mat[14];
	r.w = v.x * mat[3] + v.y * mat[7] + v.z * mat[11] + mat[15];
	return r;
}


CUDA_CALLABLE inline C_Mat44 f_Identity() {
	//return C_Mat44::kIdentity;

	C_Mat44 m;
	m.columns[0][0] = 1;
	Matrix4X4f_Identity((float32*)m.columns);
	return m;
}


CUDA_CALLABLE inline void f_Identity(mat3X3& mat) {
	mat.row0 = { 1,0,0 };
	mat.row1 = { 0,1,0 };
	mat.row2 = { 0,0,1 };
}

CUDA_CALLABLE inline void f_mat_zero(mat3X3& mat) {
	mat.row0 = {0,0,0 };
	mat.row1 = {0,0,0 };
	mat.row2 = {0,0,0 };
}

CUDA_CALLABLE inline mat4 f_mat3X3to4X4(mat3X3& mat) {
	mat4 rm = {};
	rm.m0 = { mat.row0.x, mat.row0.y, mat.row0.z, 0 };
	rm.m1 = { mat.row1.x, mat.row1.y, mat.row1.z, 0 };
	rm.m2 = { mat.row2.x, mat.row2.y, mat.row2.z, 0 };
	rm.m3 = { 0, 0, 0, 1 };
}



inline vec3 operator*(const C_Mat44& mat, const vec3& v) {
	return f_Multiply(mat, v);
};

inline vec4 operator*(const C_Mat44& mat, const vec4& v) {
	return f_Multiply(mat, v);
};

inline void operator*=(vec3& v, const C_Mat44& mat) {
	v = f_Multiply(mat, v);
};


CUDA_CALLABLE inline C_Mat44 f_构建旋转矩阵(float32 角度, const vec3& 轴) {
	float32 弧度 = M_角度转弧度(角度);

	vec3 a = vec_normalize2(轴);
	float32 s = sinf(弧度);
	float32 c = cosf(弧度);

	float32 m[4][4];

	m[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;
	m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;
	m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;
	m[0][3] = 0.0f;

	m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;
	m[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;
	m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;
	m[1][3] = 0.0f;

	m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;
	m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;
	m[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;
	m[2][3] = 0.0f;

	m[3][0] = 0.0f;
	m[3][1] = 0.0f;
	m[3][2] = 0.0f;
	m[3][3] = 1.0f;

	return Mat44(&m[0][0]);
}


//这个函数有问题 不要使用
CUDA_CALLABLE inline C_Mat44 f_构建旋转矩阵(float32 a, E_轴向 轴) {
	C_Mat44 m = f_Identity();
	
	/*旋转矩阵使用列式 旋转循序为 XYZ*/

	a = M_角度转弧度(a);
	//a = M_360角度转弧度(a);
	//====================== 行式 ==========================
	if (轴 == E_轴向::e_X) {
		m.columns[1][1] = (float32)cos(a);
		m.columns[1][2] = (float32)sin(a);
		m.columns[2][1] = (float32)-sin(a);
		m.columns[2][2] = (float32)cos(a);
	}
	else if (轴 == E_轴向::e_Y) {
		m.columns[0][0] = (float32)cos(a);
		m.columns[0][2] = (float32)-sin(a);
		m.columns[2][0] = (float32)sin(a);
		m.columns[2][2] = (float32)cos(a);
	}
	else if (轴 == E_轴向::e_Z) {
		m.columns[0][0] = (float32)cos(a);
		m.columns[0][1] = (float32)sin(a);
		m.columns[1][0] = (float32)-sin(a);
		m.columns[1][1] = (float32)cos(a);
	}

	//============== 列示 ====================
	/*if (轴 == E_轴向::e_X) {
		//m = RotationMatrix(a, Vec3(1.0, 0.0, 0.0));
		m.columns[1][1] = (float32)cos(a);
		m.columns[1][2] = (float32)-sin(a);
		m.columns[2][1] = (float32)sin(a);
		m.columns[2][2] = (float32)cos(a);
	}
	else if (轴 == E_轴向::e_Y) {
		//m = RotationMatrix(a, Vec3(0.0, 1.0, 0.0));
		m.columns[0][0] = (float32)cos(a);
		m.columns[0][2] = (float32)sin(a);
		m.columns[1][1] = 1;
		m.columns[2][0] = (float32)-sin(a);
		m.columns[2][2] = (float32)cos(a);
	}
	else if (轴 == E_轴向::e_Z) {
		//m = RotationMatrix(a, Vec3(0.0, 0.0, 1.0));

		m.columns[0][0] = (float32)cos(a);
		m.columns[0][1] = (float32)-sin(a);
		m.columns[1][0] = (float32)sin(a);
		m.columns[1][1] = (float32)cos(a);
	}*/
	
	return m;
}

CUDA_CALLABLE inline C_Mat44 f_构建欧拉角旋转矩阵(float32 angle, const vec3& a) {
	C_Mat44 m = f_Identity();
	
	/*vec3 弧度 = vec3_角度转弧度(a);


	m.columns[0][0] = cos(弧度.y) * cos(弧度.z);
	m.columns[0][1] = cos(弧度.z) * sin(弧度.x) * sin(弧度.y) - cos(弧度.x) * sin(弧度.z);
	m.columns[0][2] = sin(弧度.x) * sin(弧度.z) + cos(弧度.x) * cos(弧度.z) * sin(弧度.y);

	m.columns[1][0] = cos(弧度.y) * sin(弧度.z);
	m.columns[1][1] = cos(弧度.x) * cos(弧度.z) + sin(弧度.x) * sin(弧度.y) * sin(弧度.z);
	m.columns[1][2] = cos(弧度.x) * sin(弧度.y) * sin(弧度.z) - cos(弧度.z) * sin(弧度.z);

	m.columns[2][0] = -sin(弧度.y);
	m.columns[2][1] = cos(弧度.y) * sin(弧度.x);
	m.columns[2][2] = cos(弧度.x) * cos(弧度.y);*/
	angle = M_360角度转弧度(angle);

	vec3 axis = vec_normalize2(a);
	float s = sinf(angle);
	float c = cosf(angle);


	m.columns[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;
	m.columns[0][1] = a.x * a.y * (1.0f - c) + a.z * s;
	m.columns[0][2] = a.x * a.z * (1.0f - c) - a.y * s;
	m.columns[0][3] = 0.0f;

	m.columns[1][0] = a.x * a.y * (1.0f - c) - a.z * s;
	m.columns[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;
	m.columns[1][2] = a.y * a.z * (1.0f - c) + a.x * s;
	m.columns[1][3] = 0.0f;

	m.columns[2][0] = a.x * a.z * (1.0f - c) + a.y * s;
	m.columns[2][1] = a.y * a.z * (1.0f - c) - a.x * s;
	m.columns[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;
	m.columns[2][3] = 0.0f;

	m.columns[3][0] = 0.0f;
	m.columns[3][1] = 0.0f;
	m.columns[3][2] = 0.0f;
	m.columns[3][3] = 1.0f;


	/*m.columns[0][0] = cos(弧度.y) * cos(弧度.z);
	m.columns[1][0] = cos(弧度.z) * sin(弧度.x) * sin(弧度.y) - cos(弧度.x) * sin(弧度.z);
	m.columns[2][0] = sin(弧度.x) * sin(弧度.z) + cos(弧度.x) * cos(弧度.z) * sin(弧度.y);

	m.columns[0][1] = cos(弧度.y) * sin(弧度.z);
	m.columns[1][1] = cos(弧度.x) * cos(弧度.z) + sin(弧度.x) * sin(弧度.y) * sin(弧度.z);
	m.columns[2][1] = cos(弧度.x) * sin(弧度.y) * sin(弧度.z) - cos(弧度.z) * sin(弧度.z);

	m.columns[0][2] = -sin(弧度.y);
	m.columns[1][2] = cos(弧度.y) * sin(弧度.x);
	m.columns[2][2] = cos(弧度.x) * cos(弧度.y);*/


	return m;
}




CUDA_CALLABLE inline C_Mat44 f_构建欧拉角旋转矩阵(const vec3& a) {
	C_Mat44 m = f_Identity();

	vec3 弧度 = vec3_角度转弧度(a);


	/*m.columns[0][0] = cos(弧度.y) * cos(弧度.z);
	m.columns[0][1] = -sin(弧度.y);
	m.columns[0][2] = cos(弧度.y) * sin(弧度.z);

	m.columns[0][0] = cos(弧度.z) * sin(弧度.x) * sin(弧度.y) - cos(弧度.x) * sin(弧度.z);
	m.columns[0][1] = cos(弧度.x) * cos(弧度.z) + sin(弧度.x) * sin(弧度.y) * sin(弧度.z);
	m.columns[0][2] = cos(弧度.x) * cos(弧度.y);

	m.columns[2][0] = cos(弧度.x) * sin(弧度.y) + cos(弧度.z) * sin(弧度.x) * sin(弧度.z);
	m.columns[2][1] = cos(弧度.x) * sin(弧度.y) * sin(弧度.z) - sin(弧度.x) * cos(弧度.z);
	m.columns[2][2] = cos(弧度.x) * cos(弧度.y);*/




	m.columns[0][0] = cos(弧度.y) * cos(弧度.z);
	m.columns[0][1] = cos(弧度.z) * sin(弧度.x) * sin(弧度.y) - cos(弧度.x) * sin(弧度.z);
	m.columns[0][2] = sin(弧度.x) * sin(弧度.z) + cos(弧度.x) * cos(弧度.z) * sin(弧度.y);

	m.columns[1][0] = cos(弧度.y) * sin(弧度.z);
	m.columns[1][1] = cos(弧度.x) * cos(弧度.z) + sin(弧度.x) * sin(弧度.y) * sin(弧度.z);
	m.columns[1][2] = cos(弧度.x) * sin(弧度.y) * sin(弧度.z) - cos(弧度.z) * sin(弧度.z);

	m.columns[2][0] = -sin(弧度.y);
	m.columns[2][1] = cos(弧度.y) * sin(弧度.x);
	m.columns[2][2] = cos(弧度.x) * cos(弧度.y);
	


	/*m.columns[0][0] = cos(弧度.y) * cos(弧度.z);
	m.columns[1][0] = -sin(弧度.y);
	m.columns[2][0] = cos(弧度.y) * sin(弧度.z);

	m.columns[0][1] = cos(弧度.z) * sin(弧度.x) * sin(弧度.y) - cos(弧度.x) * sin(弧度.z);
	m.columns[1][1] = cos(弧度.x) * cos(弧度.z) + sin(弧度.x) * sin(弧度.y) * sin(弧度.z);
	m.columns[2][1] = cos(弧度.x) * cos(弧度.y);

	m.columns[0][2] = cos(弧度.x) * sin(弧度.y) + cos(弧度.z) * sin(弧度.x) * sin(弧度.z);
	m.columns[1][2] = cos(弧度.x) * sin(弧度.y) * sin(弧度.z) - sin(弧度.x) * cos(弧度.z);
	m.columns[2][2] = cos(弧度.x) * cos(弧度.y);*/



	/*m.columns[0][0] = cos(弧度.y) * cos(弧度.z);
	m.columns[0][1] = cos(弧度.z) * sin(弧度.x) * sin(弧度.y) - cos(弧度.x) * sin(弧度.z);
	m.columns[0][2] = cos(弧度.x) * sin(弧度.y) * cos(弧度.z) + sin(弧度.x) * sin(弧度.z);

	m.columns[1][0] = cos(弧度.y) * sin(弧度.z);
	m.columns[1][1] = sin(弧度.x) * sin(弧度.y) * sin(弧度.z) + cos(弧度.x) * cos(弧度.z);
	m.columns[1][2] = cos(弧度.x) * sin(弧度.y) * sin(弧度.z) - sin(弧度.z) * cos(弧度.z);

	m.columns[2][0] = -sin(弧度.y);
	m.columns[2][1] = sin(弧度.x) * cos(弧度.y);
	m.columns[2][2] = cos(弧度.x) * cos(弧度.y);*/

	return m;
}




CUDA_CALLABLE inline vec3 f_欧拉旋转矩阵构建欧拉角(const C_Mat44& a) {
	vec3 m;

	//vec3 弧度 = vec3_角度转弧度(a);


	/*m.columns[0][0] = cos(弧度.y) * cos(弧度.z);
	m.columns[0][1] = cos(弧度.z) * sin(弧度.x) * sin(弧度.y) - cos(弧度.x) * sin(弧度.z);
	m.columns[0][2] = sin(弧度.x) * sin(弧度.z) + sin(弧度.y) - cos(弧度.x) * cos(弧度.z) * sin(弧度.y);

	m.columns[1][0] = cos(弧度.y) * sin(弧度.z);
	m.columns[1][1] = cos(弧度.x) * cos(弧度.z) + sin(弧度.x) * sin(弧度.y) * sin(弧度.z);
	m.columns[1][2] = cos(弧度.x) * sin(弧度.y) * sin(弧度.z) - cos(弧度.z) * sin(弧度.z);

	m.columns[2][0] = -sin(弧度.y);
	m.columns[2][1] = cos(弧度.y) * sin(弧度.x);
	m.columns[2][2] = cos(弧度.x) * cos(弧度.y);*/

	return m;
}


Inline vec3 f_graph_向量转角度(vec3 向量) {
	vec_normalize(&向量);

	float32 弧度X = f_graph_两向量夹角弧度({ 0.0f, 向量.y, 向量.z }, { 0,0,1 });
	float32 弧度Y = f_graph_两向量夹角弧度({ 向量.x, 0, 向量.z }, { 1,0,0 });
	float32 弧度Z = f_graph_两向量夹角弧度({ 向量.x, 向量.y, 0 }, { 0,1,0 });

	if(向量.y < 0) 弧度X = M_PI - 弧度X + M_PI;
	if(向量.z < 0) 弧度Y = M_PI - 弧度Y + M_PI;
	if(向量.x < 0) 弧度Z = M_PI - 弧度Z + M_PI;

	return { 
		弧度X * vec_len(vec3{ 0.0f, 向量.y, 向量.z }), 
		弧度Y * vec_len(vec3{ 向量.x, 0, 向量.z }), 
		弧度Z * vec_len(vec3{ 向量.x, 向量.y, 0 })
	};
}


Inline vec3 f_graph_向量转角度(vec3 向量A, vec3 向量B) {

	float32 弧度X = f_graph_两向量夹角弧度({ 0.0f, 向量A.y, 向量A.z }, { 0,0,向量B.x });
	float32 弧度Y = f_graph_两向量夹角弧度({ 向量A.x, 0, 向量A.z }, { 向量B.x,0,0 });
	float32 弧度Z = f_graph_两向量夹角弧度({ 向量A.x, 向量A.y, 0 }, { 0,向量B.y,0 });

	if(向量A.y < 0) 弧度X = M_PI - 弧度X + M_PI;
	if(向量A.z < 0) 弧度Y = M_PI - 弧度Y + M_PI;
	if(向量A.x < 0) 弧度Z = M_PI - 弧度Z + M_PI;

	return { 
		弧度X * vec_len(vec3{ 0.0f, 向量A.y, 向量A.z }), 
		弧度Y * vec_len(vec3{ 向量A.x, 0, 向量A.z }), 
		弧度Z * vec_len(vec3{ 向量A.x, 向量A.y, 0 })
	};
}



/*Vec3f rotationMatrixToEulerAngles(Mat &R)
{
	float sy = sqrt(R.at<double>(0, 0) * R.at<double>(0, 0) + R.at<double>(1, 0) * R.at<double>(1, 0));
	bool singular = sy < 1e-6; // If
	float x, y, z;
	if (!singular)
	{
		x = atan2(R.at<double>(2, 1), R.at<double>(2, 2));
		y = atan2(-R.at<double>(2, 0), sy);
		z = atan2(R.at<double>(1, 0), R.at<double>(0, 0));
	}
	else
	{
		x = atan2(-R.at<double>(1, 2), R.at<double>(1, 1));
		y = atan2(-R.at<double>(2, 0), sy);
		z = 0;
	}
#if 1
	x = x * 180.0f / 3.141592653589793f;
	y = y * 180.0f / 3.141592653589793f;
	z = z * 180.0f / 3.141592653589793f;
#endif
	return Vec3f(x, y, z);
}*/


CUDA_CALLABLE inline C_Mat44 f_构建移动矩阵(const vec3& s) {
	return TranslationMatrix(Point3(s.x, s.y, s.z));
}





CUDA_CALLABLE inline C_Mat44 f_构建缩放矩阵(const vec3& s) {
	auto m = f_Identity();

	m.columns[0][0] = s.x;
	m.columns[1][1] = s.y;
	m.columns[2][2] = s.z;

	return m;
}













CUDA_CALLABLE inline C_Mat44 f_从变换构建矩阵(const vec3& l, const vec3& r, const vec3& s) {
	auto mat = f_Identity();
	auto m = f_Identity();

	m.SetTranslation(Point3(l.x, l.y, l.z));
	//C_Mat44 m = f_Identity();
	auto matX = f_构建欧拉角旋转矩阵(r.x, { 1,0,0 });
	auto matY = f_构建欧拉角旋转矩阵(r.y, { 0,1,0 });
	auto matZ = f_构建欧拉角旋转矩阵(r.z, { 0,0,1 });
	mat *= m;

	mat *= matZ;
	mat *= matY;
	mat *= matX;

	auto matS = f_构建缩放矩阵(s);
	mat *= matS;

	return mat;
}


CUDA_CALLABLE inline C_Mat44 f_mat_从四元数构建旋转矩阵(float32 angle, const vec3& r) {
	/*vec3 a = r;
	float32 s = sinf(angle);
	float32 c = cosf(angle);*/

	float32 m[4][4];

	/*m[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;
	m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;
	m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;
	m[0][3] = 0.0f;

	m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;
	m[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;
	m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;
	m[1][3] = 0.0f;

	m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;
	m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;
	m[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;
	m[2][3] = 0.0f;*/




	/*m[0][0] = a.x * a.x * (1.0f - c) + c;
	m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;
	m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;
	m[0][3] = 0.0f;

	m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;
	m[1][1] = a.y * a.y * (1.0f - c) + c;
	m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;
	m[1][3] = 0.0f;

	m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;
	m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;
	m[2][2] = a.z * a.z * (1.0f - c) + c;
	m[2][3] = 0.0f;*/



	/*m[0][0] = a.x * a.x + (1.0f - c) + c;
	m[0][1] = a.x * a.y * (1.0f - c) - a.z * s;
	m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;
	m[0][3] = 0.0f;

	m[1][0] = a.x * a.y * (1.0f - c) + a.z * s;
	m[1][1] = a.y * a.y * (1.0f - c) + c;
	m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;
	m[1][3] = 0.0f;

	m[2][0] = a.x * a.z * (1.0f - c) - a.y * s;
	m[2][1] = a.y * a.z * (1.0f - c) + a.x * s;
	m[2][2] = a.z * a.z + (1.0f - c) * c;
	m[2][3] = 0.0f;*/



	float32 xx = r.x * r.x;
	float32 yy = r.y * r.y;
	float32 zz = r.z * r.z;
	float32 xy = r.x * r.y;
	float32 wz = angle * r.z;
	float32 wy = angle * r.y;
	float32 xz = r.x * r.z;
	float32 yz = r.y * r.z;
	float32 wx = angle * r.x;

	m[0][0] = 1 - 2 * (yy+zz);
	m[0][1] = 2 * (xy - wz);
	m[0][2] = 2 * (wy + xz);
	m[0][3] = 0.0f;

	m[1][0] = 2 * (xy + wz);
	m[1][1] = 1 - 2 * (xx + zz);
	m[1][2] = 2 * (xx + yy);
	m[1][3] = 0.0f;

	m[2][0] = 2 * (xz - wy);
	m[2][1] = 2 * (yz + wx);
	m[2][2] = 1 - 2 * (xx + yy);
	m[2][3] = 0.0f;


	m[3][0] = 0.0f;
	m[3][1] = 0.0f;
	m[3][2] = 0.0f;
	m[3][3] = 1.0f;

	return Mat44(&m[0][0]);
}













inline Mat44 f_LookAtMatrix(const Point3& viewer, const Point3& target, const vec3& up) {
	// create a basis from viewer to target (OpenGL convention looking down -z)
	Vec3 forward = -Normalize(target - viewer);
	//Vec3 up(0.0f, 1.0f, 0.0f);
	Vec3 left = Normalize(Cross({up.x, up.y, up.z}, forward));
	Vec3 Up = Cross(forward, left);

	float xform[4][4] = { { left.x, left.y, left.z, 0.0f },
						{ Up.x, -Up.y, Up.z, 0.0f},
						{ forward.x, forward.y, forward.z, 0.0f},
						{ viewer.x, viewer.y, viewer.z, 1.0f} 
	};

	return AffineInverse(Mat44(&xform[0][0]));
}



/*inline Mat44 f_LookAtMatrix(const vec3& viewer, const vec3& target, const vec3& up) {
	vec3 forward = vec_normalize2(target - viewer);
	forward.x = -forward.x;
	forward.y = -forward.y;
	forward.z = -forward.z;
	//Vec3 up(0.0f, 1.0f, 0.0f);
	Vec3 left = Normalize(Cross({ up.x, up.y, up.z }, forward));
	Vec3 Up = Cross(forward, left);

	float xform[4][4] = { { left.x, left.y, left.z, 0.0f },
						{ Up.x, -Up.y, Up.z, 0.0f},
						{ forward.x, forward.y, forward.z, 0.0f},
						{ viewer.x, viewer.y, viewer.z, 1.0f}
	};

	return AffineInverse(Mat44(&xform[0][0]));
}*/


inline Mat44 f_OrthographicMatrix(float32 left, float32 right, float32 bottom, float32 top, float32 n, float32 f)
{

	float32 m[4][4] = { { 2.0f / (right - left), 0.0f, 0.0f, 0.0f },
					  { 0.0f, 2.0f / (top - bottom), 0.0f, 0.0f },
					  { 0.0f, 0.0f, -2.0f / (f - n), 0.0f },
					  { -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(f + n) / (f - n), 1.0f } };


	return Mat44(&m[0][0]);
}

















inline C_Mat44 f_创建右手转左手坐标系() {
	C_Mat44 mat = f_Identity();
	auto matR = f_构建旋转矩阵(-90.0, E_轴向::e_X);
	auto matS = f_构建缩放矩阵(vec3{ 1.0, 1.0, -1.0 });

	//mat = matR * mat;
	//mat = matS * mat;

	//return matS * matR;
	return matR * matS;
}


inline C_Mat44 f_创建左手转右手坐标系() {
	C_Mat44 mat = f_Identity();
	auto matR = f_构建旋转矩阵(90.0, E_轴向::e_X);
	auto matS = f_构建缩放矩阵(vec3{ 1.0, 1.0, -1.0 });
	//mat = matS * mat;
	//mat = matR * mat;
	//matS = f_构建缩放矩阵(vec3{ -1.0, -1.0, -1.0 });
	//mat *= matS;
	return matS * matR;
	//return matR * matS;
}





inline C_Mat44 f_创建BL右手转GL右手坐标系() {
	C_Mat44 mat = f_Identity();
	auto matR = f_构建旋转矩阵(-90.0, E_轴向::e_Z);
	auto matS = f_构建缩放矩阵(vec3{ -1.0, 1.0, 1.0 });
	//mat = matS * mat;
	//mat = matR * mat;
	//matS = f_构建缩放矩阵(vec3{ -1.0, -1.0, -1.0 });
	//mat *= matS;
	return matS * matR;
	//return matR * matS;
}










#define f_逆矩阵 AffineInverse
#define f_mat_四元数转33矩阵 RotationMatrix
#define f_mat_四元数转44矩阵 RotationMatrix
#define f_mat_差积 Cross


Mat44 f_求逆矩阵(const Mat44& mat);
void f_求逆矩阵(C_Mat33& mat);


mat3X3 f_mat_3x3转置(const mat3X3& m);
void f_mat_转换(mat3X3& m, const C_Mat33& m2);
C_Mat33 f_mat_转换(const mat3X3& m2);
mat3X3 f_mat_转换(C_Mat44& m);
void f_mat_转换(C_Mat44& m, const C_Mat33& m2);
void f_mat_转换(C_Mat44& m, const mat3X3& m2);




CUDA_CALLABLE inline C_Mat44 f_mat3x3_4X4(mat3X3 mat33) {
	C_Mat44 mat = C_Mat44::kIdentity;
	mat.columns[0][0] = mat33.row0.x;
	mat.columns[0][1] = mat33.row0.y;
	mat.columns[0][2] = mat33.row0.z;

	mat.columns[1][0] = mat33.row1.x;
	mat.columns[1][1] = mat33.row1.y;
	mat.columns[1][2] = mat33.row1.z;

	mat.columns[2][0] = mat33.row2.x;
	mat.columns[2][1] = mat33.row2.y;
	mat.columns[2][2] = mat33.row2.z;
	return mat;
}

